package fileutil

/*
#include <sys/ioctl.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>

#ifdef __APPLE__
#include <sys/disk.h>
#endif

#ifdef __linux__
#include <linux/fs.h>
#endif

typedef struct  {
	int64_t res;
	int 	status;
	char 	*err_msg;
} my_device_size_result_t;

my_device_size_result_t*
my_get_device_size(uint32_t fd)
{
	my_device_size_result_t *res =
		(my_device_size_result_t *)malloc(sizeof(my_device_size_result_t));
	if (res == NULL) {
		return NULL;
	}

	bzero(res, sizeof(my_device_size_result_t));

	unsigned long block_size = 0;

#ifdef __APPLE__
	res->status = ioctl(fd, DKIOCGETPHYSICALBLOCKSIZE, &block_size);
#endif

#ifdef __linux__
	res->status = ioctl(fd, BLKGETSIZE64, &block_size);
#endif

	if (res->status == -1) {
		res->err_msg = strerror(errno);
	}

	res->res = block_size;
	return res;
}

void
my_device_size_result_free(my_device_size_result_t *res)
{
	free(res);
}
*/
import "C"
import "errors"

func GetDeviceSize(fd uintptr) (int64, error) {
	var res *C.my_device_size_result_t
	res = C.my_get_device_size(C.uint(fd))
	if res == nil {
		return 0, errors.New("get nil result from C.my_get_device_size")
	}

	defer C.my_device_size_result_free(res)

	if res.status != 0 {
		if res.err_msg != nil {
			return 0, errors.New(C.GoString(res.err_msg))
		}

		return 0, errors.New("unknown error")
	}

	return int64(res.res), nil
}
